package org.action.order.rabbit.orderListener;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.action.order.domain.entity.ActionTicketUser;
import org.action.order.domain.pojo.ActionOrder;
import org.action.order.sercive.IActionTicketUserService;
import org.action.order.sercive.IActionUserPayService;
import org.action.order.sercive.impl.ActionOrderProcessingService;
import org.museum.api.client.ActionInventoryClient;
import org.museum.api.util.CommonResponse;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.Collections;

import static org.action.order.util.StaticVariable.*;

@Component
@Slf4j
public class OrderListener {
    @Autowired
    private ActionOrderProcessingService actionOrderProcessingService;
    @Autowired
    private IActionTicketUserService iActionTicketUserService;
    @Autowired
    private IActionUserPayService actionUserPayService;
    @Autowired
    private ActionInventoryClient actionInventoryClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private static final DefaultRedisScript<Long> Action_Script;
    static {
        Action_Script = new DefaultRedisScript<>();
        Action_Script.setLocation(new ClassPathResource("restoreStock.lua"));
        Action_Script.setResultType(Long.class);
    }

    @RabbitListener(
            concurrency = "3-5",
            bindings = @QueueBinding(
                    value = @Queue(name = Action_Order_Rabbit_Queue, durable = "true",
                            // 添加死信配置
                            arguments = {
                            @Argument(name = "x-dead-letter-exchange", value = DLX_EXCHANGE),
                            @Argument(name = "x-dead-letter-routing-key", value = DLX_ROUTING_KEY),
                    }
                    ), // 声明队列
                    exchange = @Exchange( // 声明交换机
                            name = Action_Order_Exchange
                    ),
                    key = {Action_Order_Routing_Key} // 绑定路由键
            )
    )
    @GlobalTransactional(name = "deductActionTicketTx", timeoutMills = 300000, rollbackFor = Exception.class)
    public void onOrderMessage( ActionOrder message) {
        try {
            log.info("处理订单消息: {}", message);
            actionOrderProcessingService.deductActionTicket(message);
        } catch (Exception e) {
            log.error("处理订单失败: {}", message);
            throw new RuntimeException("订单处理失败");
        }
    }

    //延迟队列进行订单超过支付时间后进行订单取消，库存恢复
    @RabbitListener(
            concurrency = "3-5",
            bindings = @QueueBinding(
                    value = @Queue(name = Action_Order_Rabbit_Delay_Queue, durable = "true"
                    ), // 声明延迟队列
                    exchange = @Exchange( // 声明延迟交换机
                            name = Action_Order_Delay_Exchange,
                            delayed =  "true"
                    ),
                    key = {Action_Order_Routing_Delay_Key} // 绑定延迟路由键
            )
    )
    @GlobalTransactional(name = "deductActionTicket", timeoutMills = 300000, rollbackFor = Exception.class)
    public void onDelayOrderMessage(String message) {
        try{
            //判断用户是否支付了订单
            boolean status=actionUserPayService.getUserOrderStatusById(Long.parseLong(message));
            if(!status){
                //用户超时未支付 TODO 1.修改订单状态为已取消 2.数据库库存回复 3.redis缓存的恢复
                //修改订单状态为已取消
                actionUserPayService.update().eq("order_id",message).eq("pay_status",0).set("pay_status",3).update();
                System.out.println("修改订单状态为已取消");
                log.debug("修改订单状态为已取消");
                //获取票的id
                ActionTicketUser actionTicketUser =iActionTicketUserService.getOne(new QueryWrapper<ActionTicketUser>().eq("id",message));
                System.out.println("获取票的id："+actionTicketUser.getActionTicketId());
                log.debug("获取票的id："+actionTicketUser.getActionTicketId());
                //调用库存微服务进行库存恢复
                CommonResponse<Integer> result =actionInventoryClient.restoreStock(actionTicketUser.getActionTicketId());
                log.debug("库存恢复结果："+result);
                if(result.getCode()!=200){
                    log.error("库存恢复失败");
                    throw new RuntimeException("库存恢复失败");
                }
                //恢复redis缓存的库存
                //TODO 执行lua脚本进行库存恢复
                //执行lua脚本
                System.out.println("执行lua脚本");
                Long res = stringRedisTemplate.execute(Action_Script,
                        Collections.emptyList(),
                        actionTicketUser.getActionTicketId().toString(), actionTicketUser.getRelativeIdentity(), actionTicketUser.getChildrenIdentity());
                int r = 0;
                if (res != null) {
                    r = res.intValue();
                }
                if(r!=1) {
                    throw new RuntimeException("库存恢复失败");
                }
            }
        }catch (Exception e){
            log.error("处理id为{}订单失败", message);
            throw new RuntimeException("处理订单失败");
        }
    }

    /*
    @RabbitListener(
            queues = DLX_QUEUE,
            concurrency = "1-3"  // 死信队列并发度通常较低
    )
    public void onDlxMessage(ActionOrder message) {
        log.error("处理死信队列消息: {}", message);
    }

     */
}
